package com.base.common.http.handler;

import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.base.common.http.constant.SocketConstant;
import com.base.common.http.model.HttpConfigModel;
import com.base.common.http.util.CloseUtils;
import com.base.common.util.StringHandler;
import com.base.common.util.StringUtils;
import com.yf.cmw.constant.BussConstant;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Date;

public class HttpHandler extends SocketAdapterHandler {
    private static final String TAG = "HttpHandler";

    private Socket socket;

    private HttpConfigModel httpConfig;
    private HttpBusinessCallback httpBusinessCallback;

    public HttpHandler(Socket socket,  HttpConfigModel httpConfig) {
        this.socket = socket;
        this.httpConfig = httpConfig;
    }

    public HttpHandler(Socket socket,  HttpConfigModel httpConfig, HttpBusinessCallback httpBusinessCallback) {
        this.socket = socket;
        this.httpConfig = httpConfig;
        this.httpBusinessCallback = httpBusinessCallback;
    }

    @Override
    public void run() {
        OutputStream outputStream = null;
        try{
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String request = bufferedReader.readLine();
            String[] httpInfoArr = null;
            if(null != request && !request.equals("")){
                Log.i(TAG,String.format("request:%s", request)); //输出一下请求的报头
                httpInfoArr = request.split(" ");//拆分出第一行的三部分内容
            }

            do{//循环是为了把剩下的请求内容读完，否则会产生异常
                request = bufferedReader.readLine();
                Log.i(TAG,String.format("request:%s", request)); //把全部报头都输出
            }while (null != request && !request.equals(""));

            outputStream = socket.getOutputStream();
            if(null == httpInfoArr || httpInfoArr.length != 3 || !httpInfoArr[0].equals("GET")){
                responseOutFileByErr(outputStream, HttpConfigModel.HTTP_STATUS_500);
            }else{
                String path = httpInfoArr[1];//取出请求的资源路径
                responseOutFileByPath(path, outputStream);
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            CloseUtils.close( outputStream, socket);
        }
    }

    private void responseOutFileByPath(String path, OutputStream outputStream) throws IOException {
        boolean isHome = false;
        if(path.equals("/") || path.equals("/index")|| path.equals("/home")){
            path = httpConfig.getDefaultFile();
            isHome = true;
        }
        String actionTips = "/action";
        if(StringHandler.isValidStr(path) && path.indexOf(actionTips) != -1){
            this.httpActionHandler(path, outputStream);
            return;
        }
        if(StringHandler.isValidStr(path) && path.indexOf("/download") != -1){
            String rootPath = getOutputRootPath(path);
            String filePath = rootPath + StringHandler.getUrlParam(path, "fileName");
            File outFile = new File(filePath);
            if(isHome && (isEmpty(path) || !outFile.exists())){
                responseOutHtml(HttpConfigModel.UN_HOME_FILE_RESPONSE, outputStream, HttpConfigModel.HTTP_STATUS_200);
            }else{
                if (outFile.exists()) { //判断文件是否存在 ，如果不存在，返回404页面
                    responseOutFile(filePath, outputStream, HttpConfigModel.HTTP_STATUS_200);
                } else { //如果文件不存在，返回404页面
                    responseOutFileByErr(outputStream, HttpConfigModel.HTTP_STATUS_404);
                }
            }
        }
    }

    private String getOutputRootPath(String path){
        String rootPath = httpConfig.getHomeDir() + "/";
        String outPutType = StringHandler.getUrlParam(path, "outputType");
        switch (outPutType){
            case "LOG_SPS": {
                rootPath = BussConstant.LOG_ADPATH;
                break;
            }
            case "LOG_PLAYER": {
                rootPath = BussConstant.DEFAULT_PLAYER_ADLOG;
                break;
            }
        }
        return rootPath;
    }

    private void httpActionHandler(String path, OutputStream outputStream) throws IOException{
        final Object result = httpBusinessCallback.handler(path);
        if(result == null) return;
        responseOutHtml(result.toString(), outputStream, HttpConfigModel.HTTP_STATUS_200);
    }

    private void responseOutFileByErr(OutputStream outputStream, int httpStatus) throws IOException {
        String errContentHtml = null;
        switch (httpStatus){
            case HttpConfigModel.HTTP_STATUS_500:{
                errContentHtml = HttpConfigModel.UN_ERR_FILE_RESPONSE;
                break;
            }  case HttpConfigModel.HTTP_STATUS_404:{
                errContentHtml = HttpConfigModel.UN_NOT_FOUND_FILE_RESPONSE;
                break;
            }
        }

        String errFile = httpConfig.getErrFile();
        if(isEmpty(errFile) || !new File(httpConfig.getHomeDir()+"/" + errFile).exists()){
            if(isEmpty(errContentHtml)) errContentHtml = HttpConfigModel.UN_NOT_FOUND_FILE_RESPONSE;
            responseOutHtml(errContentHtml, outputStream, httpStatus);
        }else{
            responseOutFile(errFile, outputStream, httpStatus);
        }
    }

    public static void responseOutHtml(String content, OutputStream os, int status) throws IOException {
        System.out.println("response:");
        System.out.println(content);
        StringBuilder stringBuilder = getHttpHeaderSet(null, status);
        stringBuilder.append(content);
        os.write(stringBuilder.toString().getBytes("UTF-8"));  //输出响应报头
        // os.write(content.getBytes());
        os.flush();
        os.close();
    }

    public static void responseOutFile(String fileName, OutputStream os, int status) throws IOException {
        System.out.println("response:");
        System.out.println(fileName);
        StringBuilder stringBuilder = getHttpHeaderSet(fileName, status);
        FileInputStream fis = new FileInputStream(fileName);
        byte[] bytes = new byte[1024];
        int len;
        os.write(stringBuilder.toString().getBytes("UTF-8"));  //输出响应报头
        while ((len = fis.read(bytes)) != -1) { //输出文件内容
            os.write(bytes, 0, len);
        }
        os.flush();
        os.close();
        fis.close();
    }

    private static StringBuilder getHttpHeaderSet(String fileName,int status) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("HTTP/1.1 " + status + " OK\r\n"); //输出状态码
        stringBuilder.append("Date: " + (new Date()).toString() + "\r\n");
        stringBuilder.append("Server: MyServer 0.0.1\r\n");  //代表服务器的软件名称
        stringBuilder.append("X-Powered-By: Hawkon\r\n");    //这行可以换成你的英文名，看起来会有点diao
        stringBuilder.append("Keep-Alive: timeout=5, max=100\r\n");
        stringBuilder.append("Connection: Keep-Alive\r\n"); //image/png
        String contentType = getContentType(fileName);
        stringBuilder.append(String.format("Content-Type: %s;charset=utf-8\r\n", contentType)); //字符串编码
        stringBuilder.append("\r\n");//多输出一个空行，用来分割报头和报体，HTTP协议要求
        return stringBuilder;
    }

    private static String getContentType(String fileName){
        if(StringUtils.isEmpty(fileName)){
            return "text/html";
        }else{
            fileName = fileName.toLowerCase();
            if(fileName.endsWith("png")){
                return "image/png";
            }else if(fileName.endsWith("jpeg") || fileName.endsWith("jpe")|| fileName.endsWith("jpg")){
                return "image/jpeg";
            }else if(fileName.endsWith("mp4") ){
                return "video/mpeg4";
            }else if(fileName.endsWith("mp3") ){
                return "audio/mp3";
            }else if(fileName.endsWith("mp2") ){
                return "audio/mp2";
            }else if(fileName.endsWith("pdf") ){
                return "application/pdf";
            }else{
                return "text/html";
            }
        }
    }

    @Override
    public void close() throws IOException {
        CloseUtils.close(socket);
        socket = null;
    }

    @Override
    int getType() {
        return SocketConstant.SOCKET_HANDLER_TYPE_HTTP;
    }
}
